#include "dialogconfig.h"

#include "oauthmanager.h"
#include "configuration.h"

#include "controls/ftlabel.h"
#include "controls/ftwidgetlist.h"
#include "controls/ftpushbutton.h"
#include "controls/ftwidgetlist.h"
#include "controls/ftcheckbox.h"
#include "controls/ftradiobutton.h"
#include "controls/fttabwidget.h"
#include "controls/ftvboxlayout.h"
#include "controls/fthboxlayout.h"
#include "controls/ftlineedit.h"
#include "controls/ftbrowser.h"
#include "controls/fttextarea.h"
#include "controls/filebrowser.h"

extern Configuration* configuration;

DialogConfig::DialogConfig() :
    RotatingDialog()
{
    content = new FTTabWidget( FTTabWidget::full_page );
    // The close button
    closeButton = new FTPushButton( tr("Back to Track@Way") );
    connect( closeButton, SIGNAL(clicked()),
              this, SLOT(accept()));
    content->addExtra( closeButton );

    buildGeneralPage();
    buildTrackingPage();
    buildBreadcrumbsPage();
    buildWaypointsPage();
    buildLanguagePage();

    // create this AFTER configuration has been read (to set tokens)
    QByteArray token;
    QByteArray tokenSecret;
    configuration->breadcrumbsToken( token, tokenSecret );
    breadcrumbs_oauth = new OauthManager(this, token, tokenSecret );
}

void DialogConfig::buildGeneralPage()
{
    general_page = new QWidget();
    content->addTab( general_page, tr("General setup...") );

    general_label = new FTLabel( tr("General setup") );

    // Create the save position checkbox
    saveposition = new FTCheckBox( tr("Remember last position") );
    saveposition->setChecked( configuration->savePosition() );
    connect( saveposition, SIGNAL(clicked(bool)),
                 this, SLOT(savePositionChanged(bool)));

    // Create the confirm internet checkbox
    internet_confirm = new FTCheckBox( tr("Ask before accessing internet") );
    internet_confirm->setChecked( configuration->internetAuthorization() );
    connect( internet_confirm, SIGNAL(clicked(bool)),
                 this, SLOT(confirmInternetChanged(bool)) );

    // Create the ads removal check
    show_ads = new FTCheckBox( tr("Show ads in message boxes") );
    show_ads->setChecked( configuration->showAds() );
    connect( show_ads, SIGNAL(clicked(bool)),
                 this, SLOT(showAdsChanged(bool)));

    // Create the gpx autostart checkbox
    gpsautostart = new FTCheckBox( tr("Initialize GPS at startup") );
    gpsautostart->setChecked( configuration->gpsAutostart() );
    connect( gpsautostart, SIGNAL(clicked(bool)),
                 this, SLOT(gpsAutostartChanged(bool)) );

    // Create the alwayson checkbox
    always_on = new FTCheckBox( tr("Keep backlight always on") );
    always_on->setChecked( configuration->screenAlwaysOn() );
    connect( always_on, SIGNAL(clicked(bool)),
                 this, SLOT(alwaysOnChanged(bool)) );

    // Create the use only satellites
    use_sats_only = new FTCheckBox( tr("Use only satellites") );
    use_sats_only->setChecked( configuration->useSatellitesOnly() );
    connect( use_sats_only, SIGNAL(clicked(bool)),
                 this, SLOT(useSatsOnlyChanged(bool)) );

    // Storage drive correction
    drive_label = new FTLabel( configuration->storageDrive() );
    drive_select = new FTPushButton( tr("select storage drive") );
    connect( drive_select, SIGNAL(clicked()),
             this, SLOT(driveClicked()) );
}

void DialogConfig::buildTrackingPage()
{
    tracking_page = new QWidget();
    content->addTab( tracking_page, tr("Tracking setup") );

    tracking_label = new FTLabel( tr("Tracking setup") );

    Configuration::tracking_mode tm = configuration->trackingMode();

    trackModeLabel = new FTLabel( tr("Tracking mode:") );
    auto_track = new FTRadioButton( tr("Automatic mode") );
    track_mode.addButton( auto_track );
    if ( tm == Configuration::automatic_trackmode )
        auto_track->setChecked(true);

    time_track = new FTRadioButton( tr("Time based mode") );
    track_mode.addButton( time_track );
    if ( tm == Configuration::time_trackmode )
        time_track->setChecked(true);

    space_track = new FTRadioButton( tr("Distance based mode") );
    track_mode.addButton( space_track );
    if ( tm == Configuration::distance_trackmode )
        space_track->setChecked(true);

    connect( &track_mode, SIGNAL( buttonClicked(QAbstractButton*) ),
                this, SLOT(trackModeSelected(QAbstractButton*)) );

    time_label = new FTLabel( tr("Interval (seconds):") );
    time_val_track = new FTLineEdit( QString("%1").arg(configuration->trackingTime()) );
    connect( time_val_track, SIGNAL(editingFinished()),
             this, SLOT(trackTimeChanged()));

    minimumDopLabel = new FTLabel( tr("Minimum valid DOP:") );
    minimumDop = new FTLineEdit( QString("%1").arg(configuration->minimumDop()) );
    connect( minimumDop, SIGNAL(editingFinished()),
             this, SLOT(minimumDopChanged()));

    space_label = new FTLabel( tr("Distance (meters):") );

    space_val_track = new FTLineEdit( QString("%1").arg(configuration->trackingDistance()) );
    connect( space_val_track, SIGNAL(editingFinished()),
             this, SLOT(trackDistanceChanged()));

    // Create the autosave checkbox
    autosave = new FTCheckBox( tr("Live Track autosave") );
    autosave->setChecked(configuration->livetrackAutosave());
    connect( autosave, SIGNAL(clicked(bool)),
                 this, SLOT(AutosaveChanged(bool)));

    // Create the calc speed checkbox
    calc_speed = new FTCheckBox( tr("Calculate missing speeds") );
    calc_speed->setChecked(configuration->calculateSpeed());
    connect( calc_speed, SIGNAL(clicked(bool)),
                 this, SLOT(calculateSpeedChanged(bool)) );

    // Altitude correction
    altitude_correction_label = new FTLabel( tr("Altitude correction") +  " (m)");
    altitude = new FTLineEdit( QString("%1").arg(configuration->altitudeCorrection() ) );
    connect( altitude, SIGNAL(textChanged(QString)),
                 this, SLOT(altitudeCorrectionChanged(QString)));

}


void DialogConfig::buildBreadcrumbsPage()
{
    breadcrumbs_page = new QWidget();
    content->addTab( breadcrumbs_page, tr("GoBreadcrumbs setup") );

    breadcrumbs_label = new FTLabel( tr("GoBreadcrumbs.com") );

    breadcrumbs_authorize = new FTPushButton();
    connect( breadcrumbs_authorize, SIGNAL(clicked()),
             this, SLOT( breadcrumbsChanged()));

    breadcrumbs_setpin = new FTPushButton( tr("Set PIN...") );
    connect( breadcrumbs_setpin, SIGNAL(clicked()),
                           this, SLOT( breadcrumbsSetpin() ));

    breadcrumbs_pin = new FTLineEdit();

    breadcrumbs_pin_requested = false;
    breadcrumbsLayout();
}

void DialogConfig::buildWaypointsPage()
{
    waypoints_page = new QWidget();
    content->addTab( waypoints_page, tr("Visualization...") );

    waypoints_label = new FTLabel( tr("Visual setup") );

    draw_waypoints = new FTCheckBox( tr("Draw waypoints") );
    draw_waypoints->setChecked(configuration->drawWaypoint());
    connect( draw_waypoints, SIGNAL(clicked(bool)),
                 this, SLOT(drawWaypointsChanged(bool)) );

    draw_waypoints_icon = new FTCheckBox( tr("Draw waypoint icons") );
    draw_waypoints_icon->setChecked(configuration->drawWaypointIcon());
    connect( draw_waypoints_icon, SIGNAL(clicked(bool)),
                 this, SLOT(drawWaypointsIconChanged(bool)) );

    draw_waypoints_name = new FTCheckBox( tr("Draw waypoint names") );
    draw_waypoints_name->setChecked(configuration->drawWaypointName());
    connect( draw_waypoints_name, SIGNAL(clicked(bool)),
                 this, SLOT(drawWaypointsNameChanged(bool)) );

    navigationProximityLabel = new FTLabel( tr("Proximity to destination (mt):"));
    navigationProximityEdit = new FTLineEdit( QString("%1").arg(configuration->navigationProximity()) );
    connect( navigationProximityEdit, SIGNAL(textEdited(QString)),
             this, SLOT(navigationProximityChanged(QString)));

    // Create the coord format radios
    coordFormatLabel = new FTLabel( tr("Use coordinate format:"));
    coordFormatDec = new FTRadioButton( tr("decimal degrees format") );
    coordFormatDms = new FTRadioButton( tr("DDD.MM.SS format") );
    coordFormatDm = new FTRadioButton( tr("DDD.MM format") );
    coordFormatUtm = new FTRadioButton( tr("UTM format") );
    coordFormat.addButton( coordFormatDec, 1 );
    coordFormat.addButton( coordFormatDms, 2 );
    coordFormat.addButton( coordFormatDm, 3 );
    coordFormat.addButton( coordFormatUtm, 4 );
    Configuration::coordinate_format cf = configuration->defaultCoordFormat();
    if ( cf == Configuration::degrees_minutes_seconds )
        coordFormatDms->setChecked( true );
    else if ( cf == Configuration::degrees_minutes )
        coordFormatDm->setChecked( true );
    else if ( cf == Configuration::utm )
        coordFormatUtm->setChecked( true );
    else
        coordFormatDec->setChecked( true );
    connect( &coordFormat, SIGNAL(buttonClicked(int)),
                 this, SLOT(coordFormatChanged(int) ) );

    // Create the "languages" selection dialog
    show_maps = new FTCheckBox( tr("Show maps on startup" ) );
    show_maps->setChecked( configuration->showMapsOnStartup() );
    connect( show_maps, SIGNAL(clicked(bool)),
             this, SLOT(showMapsSelected(bool)) );
}

void DialogConfig::buildLanguagePage()
{
    language_page = new QWidget();
    content->addTab( language_page, tr("Language setup") );

    languageLabel = new FTTextArea( tr("Select your language. 'Automatic' will use the default phone "\
                                       "language.\nPlease note that Track@Way will have to be restarted!"), 3);
    languageLabel->setAlignment( Qt::AlignCenter );
    // Create the "languages" selection dialog
    lang_widget = new FTWidgetList();
    lang_widget->setActions( false, false );

    QHash<QString, QString> langs_txt = configuration->languages();
    QString current_lang = configuration->selectedLanguage();

    foreach (QString lang, langs_txt.keys())
    {
        FTRadioButton*btl = new FTRadioButton( langs_txt.value( lang, lang ) );
        if ( lang == current_lang )
            btl->setChecked( true );
        lang_buttons.insert( btl, lang );
        langs.addButton( btl );
        lang_widget->appendWidget( btl);
    }
    connect( &langs, SIGNAL(buttonClicked(QAbstractButton*)),
             this, SLOT(langSelected(QAbstractButton*)) );

}


DialogConfig::~DialogConfig()
{
    foreach (QAbstractButton* btn, track_mode.buttons())
        track_mode.removeButton( btn );

    foreach (QAbstractButton* btn, langs.buttons())
        langs.removeButton( btn );

    foreach (QAbstractButton* btn, coordFormat.buttons())
        coordFormat.removeButton( btn );

    delete breadcrumbs_oauth;
}

void DialogConfig::accept()
{
    configuration->SaveConfig();
    RotatingDialog::accept();
}

void DialogConfig::AutosaveChanged(bool p)
{
    configuration->setLivetrackAutosave(p);
}

void DialogConfig::showAdsChanged(bool a)
{
    configuration->setShowAds(a);
    if ( configuration->showAds() != a )
        show_ads->setChecked( !a );
}

void DialogConfig::useSatsOnlyChanged(bool a)
{
    configuration->setUseSatellitesOnly(a);
    FTMessageBox::Info( tr("Configuration"), tr("Please stop and restart the GPS for the change to take effect!") );
}

void DialogConfig::showMapsSelected(bool p)
{
    configuration->setShowMapsOnStartup(p);
}

void DialogConfig::savePositionChanged(bool p)
{
    configuration->setSavePosition(p);
}

void DialogConfig::confirmInternetChanged(bool p)
{
    configuration->setInternetAuthorization(p);
}

void DialogConfig::coordFormatChanged(int)
{
    if ( coordFormatDec->isChecked() )
        configuration->setDefaultCoordFormat( Configuration::decimal );
    else if ( coordFormatDms->isChecked() )
        configuration->setDefaultCoordFormat( Configuration::degrees_minutes_seconds );
    else if ( coordFormatDm->isChecked() )
        configuration->setDefaultCoordFormat( Configuration::degrees_minutes );
    else if ( coordFormatUtm->isChecked() )
        configuration->setDefaultCoordFormat( Configuration::utm );
}

void DialogConfig::alwaysOnChanged(bool p)
{
    configuration->setScreenAlwaysOn(p);
    if ( configuration->screenAlwaysOn() != p )
        always_on->setChecked( false );
}

void DialogConfig::altitudeCorrectionChanged(QString t)
{
    int alt = t.toInt();
    configuration->setAltitudeCorrection(alt);
}

void DialogConfig::navigationProximityChanged(QString t)
{
    int alt = t.toInt();
    configuration->setNavigationProximity(alt);
}

void DialogConfig::driveClicked()
{
    QStringList filters;
    QString filename = FileBrowser::browseFilename(FileBrowser::loadMode,
                                                   tr("Select default drive"),
                                                   configuration->storageDrive(),
                                                   filters,
                                                   QDir::Drives );
    if ( filename != "" )
    {
        configuration->setStorageDrive( filename );
        drive_label->setText( filename );
    }
}

void DialogConfig::trackModeSelected(QAbstractButton* )
{
    if ( auto_track->isChecked() )
        configuration->setTrackingMode( Configuration::automatic_trackmode );
    else if ( time_track->isChecked() )
        configuration->setTrackingMode( Configuration::time_trackmode );
    else if ( space_track->isChecked() )
        configuration->setTrackingMode( Configuration::distance_trackmode );
}

void DialogConfig::trackTimeChanged()
{
    configuration->setTrackingTime( time_val_track->text().toInt() );
}

void DialogConfig::minimumDopChanged()
{
    configuration->setMinimumDop( minimumDop->text().toInt() );
    minimumDop->setText( QString("%1").arg( configuration->minimumDop() ) );
}

void DialogConfig::trackDistanceChanged()
{
    configuration->setTrackingDistance( space_val_track->text().toInt() );
}

void DialogConfig::calculateSpeedChanged(bool p)
{
    configuration->setCalculateSpeed(p);
}


void DialogConfig::breadcrumbsChanged()
{
    if ( configuration->breadcrumbsAuthorized() )
    {
        // remove auth
        if ( FTMessageBox::Yesno( "Breadcrumbs", tr("Really forget authorization?") ) )
        {
            QByteArray dummy("");
            configuration->setBreadcrumbsToken( dummy, dummy );
            configuration->setBreadcrumbsAuthorized( false );
            breadcrumbsLayout();
        }
    }
    else
    {
        // do auth
        if ( breadcrumbs_oauth->getRequestToken() )
        {
            FTMessageBox::Info( "Breadcrumbs",
                                tr("You will now switch to the browser: login, and note your PIN, you will have to input it here!") );
            QString url = breadcrumbs_oauth->getAuthUrl();
            FTBrowser browser( url );
            browser.exec();
            breadcrumbs_pin_requested = true;
            breadcrumbsLayout();
        }
        else
        {
            QByteArray dummy("");
            configuration->setBreadcrumbsToken( dummy, dummy );
            configuration->setBreadcrumbsAuthorized( false );
            FTMessageBox::Error( "Breadcrumbs",
                                tr("Unable to authorize with www.gobreadcrumbs.com!") );
         }

    }
}

void DialogConfig::breadcrumbsSetpin()
{
    QByteArray pin = breadcrumbs_pin->text().toAscii();
    if ( breadcrumbs_oauth->getAccessToken( pin ) )
    {
        QByteArray breadcrumbs_token;
        QByteArray breadcrumbs_tokenSecret;
        breadcrumbs_oauth->getToken( breadcrumbs_token, breadcrumbs_tokenSecret );
        configuration->setBreadcrumbsAuthorized( true );
        configuration->setBreadcrumbsToken(breadcrumbs_token, breadcrumbs_tokenSecret);
        breadcrumbs_pin_requested = false;
        breadcrumbsLayout();
        FTMessageBox::Info( "Breadcrumbs", tr("You are now authorized to use www.gobreadcrumbs.com!") );
    }
    else
    {
        QByteArray dummy("");
        configuration->setBreadcrumbsToken( dummy, dummy );
        configuration->setBreadcrumbsAuthorized( false );
        FTMessageBox::Error( "Breadcrumbs", tr("Sorry but PIN is invalid!") );
    }
}

void DialogConfig::gpsAutostartChanged(bool p)
{
    configuration->setGpsAutostart(p);
}

void DialogConfig::drawWaypointsChanged(bool p)
{
    configuration->setDrawWaypoint(p);
}

void DialogConfig::drawWaypointsIconChanged(bool p)
{
    configuration->setDrawWaypointIcon(p);
}

void DialogConfig::drawWaypointsNameChanged(bool p)
{
    configuration->setDrawWaypointName(p);
}

void DialogConfig::langSelected(QAbstractButton* b)
{
    if ( lang_buttons.contains( (FTRadioButton*)b ) )
    {
        QString lang = lang_buttons.value( (FTRadioButton*)b, "" );
        configuration->setSelectedLanguage( lang );
        FTMessageBox::Info(tr("Language set"), tr("Please restart Track@Way to load the language!") );
    }
}


void DialogConfig::breadcrumbsLayout()
{
    bool auth = configuration->breadcrumbsAuthorized();

    if ( auth )
    {
        breadcrumbs_authorize->setVisible(true);
        breadcrumbs_pin->setVisible(false);
        breadcrumbs_setpin->setVisible(false);
        breadcrumbs_authorize->setText( tr("Remove authorization") );
    }
    else
    {
        if ( !breadcrumbs_pin_requested )
        {
            breadcrumbs_authorize->setVisible(true);
            breadcrumbs_pin->setVisible(false);
            breadcrumbs_setpin->setVisible(false);
            breadcrumbs_authorize->setText( tr("Authorize...") );
        }
        else
        {
            breadcrumbs_authorize->setVisible(false);
            breadcrumbs_pin->setVisible(true);
            breadcrumbs_setpin->setVisible(true);
        }
    }
}

QLayout* DialogConfig::createVertical()
{
    FTVBoxLayout* vgrid;
    FTHBoxLayout* hgrid;

    // General page
    if ( general_page->layout() != NULL )
        delete general_page->layout();
    vgrid = new FTVBoxLayout();
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( general_label );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( saveposition );
    vgrid->addWidget( gpsautostart );
    vgrid->addWidget( internet_confirm );
    vgrid->addWidget( always_on );
    vgrid->addWidget( use_sats_only );
    vgrid->addWidget( show_ads );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( drive_select );
    hgrid->addWidget( drive_label );
    vgrid->addLayout( hgrid );
    vgrid->addStretch();
    general_page->setLayout( vgrid );

    // Tracking page
    if ( tracking_page->layout() != NULL )
        delete tracking_page->layout();
    vgrid = new FTVBoxLayout();
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( tracking_label );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( autosave );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( minimumDopLabel );
    hgrid->addWidget( minimumDop );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( trackModeLabel );
    vgrid->addWidget( calc_speed );
    vgrid->addWidget( auto_track );
    vgrid->addWidget( time_track );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( time_label );
    hgrid->addWidget( time_val_track );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( space_track );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( space_label );
    hgrid->addWidget( space_val_track );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( altitude_correction_label );
    vgrid->addWidget( altitude );
    vgrid->addStretch();
    tracking_page->setLayout( vgrid );

    // GoBreadcrumbs page
    if ( breadcrumbs_page->layout() != NULL )
        delete breadcrumbs_page->layout();
    vgrid = new FTVBoxLayout();
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( breadcrumbs_label );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( breadcrumbs_authorize );
    vgrid->addWidget( breadcrumbs_pin );
    vgrid->addWidget( breadcrumbs_setpin );
    vgrid->addStretch();
    breadcrumbs_page->setLayout( vgrid );

    // Waypoints page
    if ( waypoints_page->layout() != NULL )
        delete waypoints_page->layout();
    vgrid = new FTVBoxLayout();
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( waypoints_label );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( draw_waypoints );
    vgrid->addWidget( draw_waypoints_name );
    vgrid->addWidget( draw_waypoints_icon );
    vgrid->addWidget( navigationProximityLabel );
    vgrid->addWidget( navigationProximityEdit );
    vgrid->addWidget( coordFormatLabel );
    vgrid->addWidget( coordFormatDec );
    vgrid->addWidget( coordFormatDms );
    vgrid->addWidget( coordFormatDm );
    vgrid->addWidget( coordFormatUtm );
    vgrid->addWidget( show_maps );
    vgrid->addStretch();
    waypoints_page->setLayout( vgrid );

    // Language page
    if ( language_page->layout() != NULL )
        delete language_page->layout();
    vgrid = new FTVBoxLayout();
    vgrid->addWidget( languageLabel );
    foreach (FTRadioButton* btn, lang_buttons.keys() )
        vgrid->addWidget( btn );
    vgrid->addStretch();
    language_page->setLayout( vgrid );

    vgrid = new FTVBoxLayout();
    vgrid->addWidget( content );
    return vgrid;
}

QLayout* DialogConfig::createHorizontal()
{
    return createVertical();
}
